<!DOCTYPE html>
<html lang=en style="font-size: 37.5px">
<head>
    <meta charset=utf-8>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <meta content="yes" name="apple-mobile-web-app-capable"/>
    <meta content="black" name="apple-mobile-web-app-status-bar-style"/>
    <meta content="telephone=no" name="format-detection"/>
    <title>人脸检测</title>
    <script src="https://cdn.jsdelivr.net/gh/eduardolundgren/tracking.js/build/tracking-min.js"></script>
    <script src="https://cdn.jsdelivr.net/gh/eduardolundgren/tracking.js/build/data/face-min.js"></script>
</head>
<style>
    .face-capture {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
    }

    .face-capture video, .face-capture canvas {
        position: fixed;
        top: 0;
        bottom: 0;
        left: 0;
        right: 0;
        width: 100%;
        height: 100%;
        object-fit: cover;
        z-index: 2;
        background-repeat: no-repeat;
        background-size: 100% 100%;
    }
    video {
        transform: rotateY(180deg);
        -webkit-transform: rotateY(180deg); /* Safari 和 Chrome */
        -moz-transform: rotateY(180deg);
    }
    .face-capture canvas {
        z-index: 2;
    }

    .face-capture .img-cover {
        position: fixed;
        top: 0;
        bottom: 0;
        left: 0;
        right: 0;
        width: 100%;
        height: 100%;
        object-fit: cover;
        z-index: 2;
        background-repeat: no-repeat;
        background-size: 100% 100%;
    }

    .face-capture .rect {
        border: 2px solid #0aeb08;
        position: fixed;
        z-index: 3;
    }

    .face-capture .control-container {
        margin-top: 10rem;
        position: relative;
        width: 100%;
        height: 100%;
        object-fit: cover;
        z-index: 4;
        background-repeat: no-repeat;
        background-size: 100% 100%;
    }

    .face-capture .title {
        text-align: center;
        color: white;
        margin: 1.6rem auto;
        font-size: 18px;
    }

    .face-capture .close {
        width: 0.8rem;
        height: 0.8rem;
    }
</style>
<body>
<div id="app">
    <div v-show="showContainer" class="face-capture" id="face-capture">
        <video ref="refVideo" id="video" autoplay></video>
        <img src="/work_main/images/video-cover.png" alt="cover" class="img-cover"/>
        <div class="control-container face-capture">
            <h2 class="title" style="z-index: 99999">{{scanTip}}</h2>
            <img class="close" src="/work_main/images/address_edit_clear.png" style="z-index: 99999" alt="" @click="closebtn"/>
            <canvas ref="refCanvas" :width="screenSize.width" :height="screenSize.height"
                    :style="{opacity: 0}"></canvas>
        </div>
        <div class="rect" v-for="item in profile"
             :style="{ width: item.width + 'px', height: item.height + 'px', left: item.left + 'px', top: item.top + 'px'}"></div>
    </div>
    <img v-show="!showContainer" :src="imgUrl"/>
</div>
</body>
<script src="https://cdn.bootcss.com/vue/2.5.21/vue.min.js"></script>
<script src="https://cdn.staticfile.org/axios/0.18.0/axios.min.js"></script>
<script>

  const app = new Vue({
    el: "#app",
    data() {
      return {
        screenSize: {width: window.screen.width, height: window.screen.height},
        URL: null,
        streamIns: null,        // 视频流
        showContainer: true,   // 显示
        tracker: null,
        tipFlag: false,         // 提示用户已经检测到
        flag: false,            // 判断是否已经拍照
        context: null,          // canvas上下文
        profile: [],            // 轮廓
        removePhotoID: null,    // 停止转换图片
        scanTip: '正在启动...',// 提示文字
        imgUrl: null              // base64格式图片
      }
    },
    mounted() {
      let token = this.getCookie("token");
      if (token != null) {
        this.playVideo()
      } else {
        this.scanTip = "请先登录"
      }
    },
    methods: {
      playVideo() {
        //environment后置摄像头
        this.getUserMedia({
          video: {
            sourceId: 'default', width: {min: 1024, ideal: 1280, max: 1920},
            height: {min: 776, ideal: 720, max: 1080}, facingMode: {exact: "user"}
          }     /* 前置优先 */
        }, this.success, this.error)
      },
      getCookie(name) {
        var arr, reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");
        if (arr = document.cookie.match(reg))
          return unescape(arr[2]);
        else
          return null;
      },
      // 访问用户媒体设备
      getUserMedia(constrains, success, error) {
        this.scanTip = "打开摄像头中"
        var self = this;
        if (navigator.mediaDevices === undefined) {
          navigator.mediaDevices = {};
        }
        if (navigator.mediaDevices.getUserMedia === undefined) {
          navigator.mediaDevices.getUserMedia = function (constraints) {
            var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia || navigator.oGetUserMedia;
            if (!getUserMedia) {
              return Promise.reject(new Error('getUserMedia is not implemented in this browser'));
            }
            return new Promise(function (resolve, reject) {
              getUserMedia.call(navigator, constraints, resolve, reject);
            });
          }
        }
        if (window.stream) {
          window.stream.getTracks().forEach(track => {
            track.stop();
          });
        }
        navigator.mediaDevices.getUserMedia(constrains)
          .then(success)
          .catch(error);
      },
      success(stream) {
        this.streamIns = stream
        // webkit内核浏览器
        this.URL = window.URL || window.webkitURL
        if ("srcObject" in this.$refs.refVideo) {
          this.$refs.refVideo.srcObject = stream
        } else {
          this.$refs.refVideo.src = this.URL.createObjectURL(stream)
        }
        this.$refs.refVideo.onloadedmetadata = e => {
          this.$refs.refVideo.play()
          this.initTracker()
        }
      },
      error(e) {
        this.scanTip = "访问用户媒体失败" + e.name + "," + e.message
      },
      // 人脸捕捉
      initTracker() {
        this.context = this.$refs.refCanvas.getContext("2d")    // 画布
        this.tracker = new tracking.ObjectTracker(['face'])     // tracker实例
        this.tracker.setStepSize(1.7)                       // 设置步长
        this.tracker.on('track', this.handleTracked)            // 绑定监听方法
        try {
          tracking.track('#video', this.tracker)      // 开始追踪
        } catch (e) {
          this.scanTip = "访问用户媒体失败，请重试"
        }
      },
      // 追踪事件
      handleTracked(e) {
        if (e.data.length === 0) {
          this.scanTip = '未检测到人脸'
        } else {
          this.$refs.refVideo.pause();
          this.scanTip = '检测人脸成功，正在识别中...'
          this.tackPhoto()
        }
      },
      // 拍照
      tackPhoto() {
        this.context.drawImage(this.$refs.refVideo, 0, 0, this.screenSize.width, this.screenSize.height)
        // 保存为base64格式
        this.imgUrl = this.saveAsPNG(this.$refs.refCanvas)
        this.upPhoto(this.imgUrl)
      },
      // 保存为png,base64格式图片
      saveAsPNG(c) {
        return c.toDataURL('image/png', 0.2)
      },
      upPhoto: function (imgBase64) {
        this.tracker && this.tracker.removeListener('track', this.handleTracked)
        this.tracker = null
        this.context = null
        //获得Canvas对象
        var formData = new FormData();
        formData.append("file", imgBase64);
        axios.post('/work_main/api/face_search', formData)
          .then(res => {
            let text = res.data
            if (text.code === 1) {
              if (text.data == null) {
                this.scanTip = "人脸不正确"
                return;
              }
              var name = text.data.name;
              var htmlData = "姓名：" + name
              var similar = text.data.similarValue;
              htmlData += "相似度：" + similar + "%";
              var age = text.data.age;
              htmlData += "年龄：" + age
              var gender = text.data.gender;
              htmlData += "性别：" + gender
              this.scanTip = htmlData
            } else {
              this.scanTip = "人脸不匹配";
            }
          }).catch(error => { // 请求失败处理
          this.scanTip = JSON.stringify(error)
        });
      },
      // 关闭并清理资源
      closebtn() {
        history.back(-1)
      }
    }
  })

</script>
</html>